package com.ccrfid.rmc6.lbservice3.manager;

import com.ccrfid.rmc6.entity.alarm.AlarmRuleEntity;
import com.ccrfid.rmc6.entity.device.AlerterEntity;
import com.ccrfid.rmc6.entity.personnel.PersonnelEntity;
import com.ccrfid.rmc6.entity.personnel.PersonnelMoveEntity;
import com.ccrfid.rmc6.entity.poi.PoiLocationEntity;
import com.ccrfid.rmc6.lbservice3.mq.*;
import com.ccrfid.rmc6.lbservice3.pojo.locate.PersonnelLocateInfo;
import com.ccrfid.rmc6.lbservice3.pojo.msg.MsgLocate;
import com.ccrfid.rmc6.repository.personnel.PersonnelMoveRepository;
import com.ccrfid.rmc6.service.alarm.AlarmRuleService;
import com.ccrfid.rmc6.service.amq.MqMsgProducer;
import com.ccrfid.rmc6.service.personnel.PersonnelService;
import com.ccrfid.rmc6.service.poi.PoiLocationService;
import com.ccrfid.rmc6.util.GeomUtil;
import com.ccrfid.rmc6.util.JsonUtil;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Transactional
public class AlarmLinkageManager {
    private static final Logger logger = LoggerFactory.getLogger(AlarmLinkageManager.class);

    @Autowired
    private EventBus eventBus;
    @Autowired
    private PersonnelService personnelService;
    @Autowired
    private PoiLocationService poiLocationService;
    @Autowired
    private AlarmRuleService alarmRuleService;
    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private MqMsgProducer mqMsgProducer;

    @Autowired
    private PersonnelMoveRepository personnelMoveRepository;

    private Map<String, AlarmLinkageCloseDto> tagCacheMap;

    @PostConstruct
    private void init() {
        eventBus.register(this);
        tagCacheMap =  new ConcurrentHashMap<>();
    }

    @Subscribe
    public void onMqPersonnelAlarm(MqPersonnelAlarm personnelAlarm) {
        PoiLocationEntity locationEntity = poiLocationService.getPoiLocationById(personnelAlarm.getLocationId());
        AlarmRuleEntity alarmRuleEntity = alarmRuleService.getAlarmRule(personnelAlarm.getRuleId());
        PersonnelEntity personnelEntity = personnelService.getPersonnelById(personnelAlarm.getPersonnelId());
        if (locationEntity != null && alarmRuleEntity != null && personnelEntity != null ) {
            if(alarmRuleEntity.getAlarmLinkageMode().contains("423")){
                AlerterEntity alerterEntity = getAlerter(locationEntity.getId());
                AlarmLinkageDto alarmLinkageDto = new AlarmLinkageDto();
                if(alerterEntity!=null){
                    alarmLinkageDto.setIp(alerterEntity.getIp());
                    alarmLinkageDto.setPort(alerterEntity.getPort());
                    alarmLinkageDto.setStatus(1);//开启
                    if(tagCacheMap.containsKey(alerterEntity.getIp())){
                        AlarmLinkageCloseDto alarmLinkageCloseDto = tagCacheMap.get(alerterEntity.getIp());
                        Set<Long> personnelListDtoList = alarmLinkageCloseDto.getPersonnelIdList();
                        if(!personnelListDtoList.contains(personnelEntity.getId())){
                            personnelListDtoList.add(personnelEntity.getId());
                            alarmLinkageCloseDto.setPersonnelIdList(personnelListDtoList);
                            tagCacheMap.put(alerterEntity.getIp(),alarmLinkageCloseDto);
                        }
                    }else{
                        AlarmLinkageCloseDto alarmLinkageCloseDto = new AlarmLinkageCloseDto();
                        alarmLinkageCloseDto.setIp(alerterEntity.getIp());
                        alarmLinkageCloseDto.setPort(alerterEntity.getPort());
                        alarmLinkageCloseDto.setLocationId(locationEntity.getId());
                        Set<Long> personnelListDtoList = new HashSet<>();
                        personnelListDtoList.add(personnelEntity.getId());
                        alarmLinkageCloseDto.setPersonnelIdList(personnelListDtoList);
                        tagCacheMap.put(alerterEntity.getIp(),alarmLinkageCloseDto);
                    }
                    String msg = JsonUtil.INSTANCE.writeValueAsString(alarmLinkageDto);
                    mqMsgProducer.send2Topic("personnel_alarm_linkage", msg);
                }
            }
        }
    }

    public AlerterEntity getAlerter(Long locatinoId){
        String sql  =  "select a.* from poi_location t left join d_alerter a " +
                "on st_contains(t.location_polygon, a.pos) and a.floor_number = t.floor_number where t.id = " + locatinoId;

        List<AlerterEntity> content = entityManager.createNativeQuery(sql, AlerterEntity.class)
                .getResultList();
        if(content.size() > 0){
            return content.get(0);
        }else {
            return new AlerterEntity();
        }
    }



    @Subscribe
    public void onPersonnelLocateInfo(PersonnelLocateInfo locateInfo) {
        if (locateInfo.getPersonnelId() != null && tagCacheMap.size()>0) {
            MsgLocate msgLocate = locateInfo.getMsgLocate();
            if (msgLocate.getFrontPos() != null) {
                for(String key : tagCacheMap.keySet()){
                    AlarmLinkageCloseDto alarmLinkageCloseDto = tagCacheMap.get(key);
                    PoiLocationEntity locationEntity = poiLocationService.getPoiLocationById(alarmLinkageCloseDto.getLocationId());
                    if(locationEntity.getLocationPolygon().contains(msgLocate.getFrontPos())){
                        if(msgLocate.getCurrentPos() == null || !locationEntity.getLocationPolygon().contains(msgLocate.getCurrentPos())){
                            Set<Long> personnelList = alarmLinkageCloseDto.getPersonnelIdList();
                            if(personnelList.contains(locateInfo.getPersonnelId())){
                                personnelList.remove(locateInfo.getPersonnelId());
                            }
                            if(personnelList.size() == 0){//当告警器下无人员 解除告警
                                AlarmLinkageDto alarmLinkageDto = new AlarmLinkageDto();
                                alarmLinkageDto.setIp(alarmLinkageCloseDto.getIp());
                                alarmLinkageDto.setPort(alarmLinkageCloseDto.getPort());
                                alarmLinkageDto.setStatus(0);//解除
                                String msg = JsonUtil.INSTANCE.writeValueAsString(alarmLinkageDto);
                                mqMsgProducer.send2Topic("personnel_alarm_linkage", msg);
                            }
                        }
                    }
                }
            }else if(msgLocate.getFrontPos() == null && msgLocate.getCurrentPos() == null){
                Long id = personnelMoveRepository.getMaxIdByPersonnelId(locateInfo.getPersonnelId());
                PersonnelMoveEntity personnelMoveEntity = personnelMoveRepository.getById(id);
                for(String key : tagCacheMap.keySet()){
                    AlarmLinkageCloseDto alarmLinkageCloseDto = tagCacheMap.get(key);
                    PoiLocationEntity locationEntity = poiLocationService.getPoiLocationById(alarmLinkageCloseDto.getLocationId());
                    if (locationEntity.getLocationPolygon().contains(
                        GeomUtil.INSTANCE.createPoint(personnelMoveEntity.getCurrentX(), personnelMoveEntity.getCurrentY()))){
                        Set<Long> personnelList = alarmLinkageCloseDto.getPersonnelIdList();
                        if(personnelList.contains(locateInfo.getPersonnelId())){
                            personnelList.remove(locateInfo.getPersonnelId());
                        }
                        if(personnelList.size() == 0){//当告警器下无人员 解除告警
                            AlarmLinkageDto alarmLinkageDto = new AlarmLinkageDto();
                            alarmLinkageDto.setIp(alarmLinkageCloseDto.getIp());
                            alarmLinkageDto.setPort(alarmLinkageCloseDto.getPort());
                            alarmLinkageDto.setStatus(0);//解除
                            String msg = JsonUtil.INSTANCE.writeValueAsString(alarmLinkageDto);
                            mqMsgProducer.send2Topic("personnel_alarm_linkage", msg);
                        }
                    }

                }

            }
        }
    }
}
